ποΈGitΠ―ΡΠ°ποΈ
Node / meshtastic / Meshtastic-Android / files / feature / firmware / src / commonTest / kotlin / org / meshtastic / feature / firmware / ota / dfu / SecureDfuProtocolTest.kt
Displaying Raw β’ Download
feature/firmware/src/commonTest/kotlin/org/meshtastic/feature/firmware/ota/dfu/SecureDfuProtocolTest.kt 9fa9f1e341ee8d2c8fd9fabf9253b2f012fc8c95 (9fa9f1e3) Text, 17.04 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.firmware.ota.dfu
Tff7b72import T7ee787kotlinx.serialization.json.Json
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertIs
Tff7b72import T7ee787kotlin.test.assertNull
Tff7b72import T7ee787kotlin.test.assertTrue
Tff7b72private Tff7b72val Te6edf3json Tff7b72= Te6edf3Json Tb4b4b4{ Te6edf3ignoreUnknownKeys Tff7b72= Tff7b72true Tb4b4b4}
Tff7b72class T56d364SecureDfuProtocolTest Tb4b4b4{
T8b949e// ββ CRC-32 ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`CRC-32 of empty data is zero`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3ByteArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`CRC-32 standard check vector - 123456789`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Standard CRC-32/ISO-HDLC check value for "123456789" is 0xCBF43926
Tff7b72val Te6edf3data Tff7b72= Ta5d6ff"Ta5d6ff123456789Ta5d6ff"Tb4b4b4.Te6edf3encodeToByteArrayTb4b4b4(Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3xCBF43926Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`CRC-32 with seed accumulates across segments`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3data Tff7b72= Ta5d6ff"Ta5d6ffHello, World!Ta5d6ff"Tb4b4b4.Te6edf3encodeToByteArrayTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3full Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72val Te6edf3firstHalf Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3length Tff7b72= T79c0ff7Tb4b4b4)
Tff7b72val Te6edf3accumulated Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3offset Tff7b72= T79c0ff7Tb4b4b4, Te6edf3seed Tff7b72= Te6edf3firstHalfTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3fullTb4b4b4, Te6edf3accumulatedTb4b4b4, Ta5d6ff"Ta5d6ffSeeded CRC must equal whole-buffer CRCTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`CRC-32 offset and length slice correctly`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3wrapper Tff7b72= Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3xFFTb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x02Tb4b4b4, T79c0ff0Te6edf3x03Tb4b4b4, T79c0ff0Te6edf3xFFTb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3sliced Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3wrapperTb4b4b4, Te6edf3offset Tff7b72= T79c0ff1Tb4b4b4, Te6edf3length Tff7b72= T79c0ff3Tb4b4b4)
Tff7b72val Te6edf3direct Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x02Tb4b4b4, T79c0ff0Te6edf3x03Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3directTb4b4b4, Te6edf3slicedTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`CRC-32 single byte is deterministic`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x42Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x42Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`CRC-32 different data produces different CRC`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3DfuCrc32Tb4b4b4.Te6edf3calculateTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x02Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3a Tff7b72!Tff7b72= Te6edf3bTb4b4b4)
Tb4b4b4}
T8b949e// ββ intToLeBytes / readIntLe βββββββββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`intToLeBytes produces correct little-endian byte order`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3bytes Tff7b72= Te6edf3intToLeBytesTb4b4b4(T79c0ff0Te6edf3x01020304Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3x04Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3bytesTff7b72[T79c0ff0Tff7b72]Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3x03Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3bytesTff7b72[T79c0ff1Tff7b72]Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3x02Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3bytesTff7b72[T79c0ff2Tff7b72]Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3bytesTff7b72[T79c0ff3Tff7b72]Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`intToLeBytes and readIntLe round-trip for zero`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3roundTripIntTb4b4b4(T79c0ff0Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`intToLeBytes and readIntLe round-trip for positive value`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3roundTripIntTb4b4b4(T79c0ff0Te6edf3x12345678Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`intToLeBytes and readIntLe round-trip for Int MAX_VALUE`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3roundTripIntTb4b4b4(Tffa657IntTb4b4b4.Te6edf3MAX_VALUETb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`intToLeBytes and readIntLe round-trip for negative value`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3roundTripIntTb4b4b4(Tff7b72-T79c0ff1Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`readIntLe reads from non-zero offset`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3buf Tff7b72= Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x00Tb4b4b4, T79c0ff0Te6edf3x04Tb4b4b4, T79c0ff0Te6edf3x03Tb4b4b4, T79c0ff0Te6edf3x02Tb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3x01020304Tb4b4b4, Te6edf3bufTb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffroundTripIntTb4b4b4(Te6edf3valueTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(Te6edf3valueTb4b4b4, Te6edf3intToLeBytesTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4.Te6edf3readIntLeTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)
Tb4b4b4}
T8b949e// ββ DfuResponse.parse ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Unknown when data is too short`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3UnknownTff7b72>Tb4b4b4(Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x60Tb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Unknown when first byte is not RESPONSE_CODE`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3UnknownTff7b72>Tb4b4b4(Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Failure when result is not SUCCESS`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3data Tff7b72= Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_OBJECTTb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4, Te6edf3resultTb4b4b4.Te6edf3opcodeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_OBJECTTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3resultCodeTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Success for CREATE opcode`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3result Tff7b72= Te6edf3parseSuccessForTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3SuccessTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4, Te6edf3resultTb4b4b4.Te6edf3opcodeTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Success for EXECUTE opcode`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3result Tff7b72= Te6edf3parseSuccessForTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3EXECUTETb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3SuccessTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3EXECUTETb4b4b4, Te6edf3resultTb4b4b4.Te6edf3opcodeTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Success for SET_PRN opcode`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3result Tff7b72= Te6edf3parseSuccessForTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3SET_PRNTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3SuccessTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Success for ABORT opcode`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3result Tff7b72= Te6edf3parseSuccessForTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3ABORTTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3SuccessTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns SelectResult for SELECT success`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3maxSize Tff7b72= Te6edf3intToLeBytesTb4b4b4(T79c0ff4T79c0ff0T79c0ff9T79c0ff6Tb4b4b4)
Tff7b72val Te6edf3offset Tff7b72= Te6edf3intToLeBytesTb4b4b4(T79c0ff5T79c0ff1T79c0ff2Tb4b4b4)
Tff7b72val Te6edf3crc Tff7b72= Te6edf3intToLeBytesTb4b4b4(T79c0ff0Te6edf3xDEADBEEFTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3data Tff7b72=
Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3DfuOpcodeTb4b4b4.Te6edf3SELECTTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3SUCCESSTb4b4b4) Tff7b72+ Te6edf3maxSize Tff7b72+ Te6edf3offset Tff7b72+ Te6edf3crc
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3SelectResultTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff4T79c0ff0T79c0ff9T79c0ff6Tb4b4b4, Te6edf3resultTb4b4b4.Te6edf3maxSizeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff5T79c0ff1T79c0ff2Tb4b4b4, Te6edf3resultTb4b4b4.Te6edf3offsetTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3xDEADBEEFTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3resultTb4b4b4.Te6edf3crc32Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Failure for SELECT when payload too short`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3short Tff7b72= Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3DfuOpcodeTb4b4b4.Te6edf3SELECTTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3SUCCESSTb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x02Tb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3shortTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_PARAMETERTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3resultCodeTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns ChecksumResult for CALCULATE_CHECKSUM success`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3offset Tff7b72= Te6edf3intToLeBytesTb4b4b4(T79c0ff1T79c0ff0T79c0ff2T79c0ff4Tb4b4b4)
Tff7b72val Te6edf3crc Tff7b72= Te6edf3intToLeBytesTb4b4b4(T79c0ff0Te6edf3x12345678Tb4b4b4)
Tff7b72val Te6edf3data Tff7b72=
Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3DfuOpcodeTb4b4b4.Te6edf3CALCULATE_CHECKSUMTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3SUCCESSTb4b4b4) Tff7b72+ Te6edf3offset Tff7b72+ Te6edf3crc
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3ChecksumResultTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff1T79c0ff0T79c0ff2T79c0ff4Tb4b4b4, Te6edf3resultTb4b4b4.Te6edf3offsetTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff0Te6edf3x12345678Tb4b4b4, Te6edf3resultTb4b4b4.Te6edf3crc32Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Failure for CALCULATE_CHECKSUM when payload too short`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3short Tff7b72= Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3DfuOpcodeTb4b4b4.Te6edf3CALCULATE_CHECKSUMTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3SUCCESSTb4b4b4, T79c0ff0Te6edf3x01Tb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3shortTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_PARAMETERTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3resultCodeTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`Unknown DfuResponse preserves raw bytes`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3raw Tff7b72= Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3xAATb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff0Te6edf3xBBTb4b4b4.Te6edf3toByteTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3rawTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3UnknownTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3contentEqualsTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3rawTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffparseSuccessForTb4b4b4(Te6edf3opcodeTb4b4b4: Tffa657ByteTb4b4b4)Tb4b4b4: Te6edf3DfuResponse Tff7b72=
Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3opcodeTb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3SUCCESSTb4b4b4)Tb4b4b4)
T8b949e// ββ DfuManifest deserialization βββββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuManifest deserializes application entry`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3manifest Tff7b72=
Te6edf3jsonTb4b4b4.Te6edf3decodeFromStringTff7b72<Te6edf3DfuManifestTff7b72>Tb4b4b4(
Ta5d6ff"""Ta5d6ff{Ta5d6ff"Ta5d6ffmanifestTa5d6ff"Ta5d6ff:{Ta5d6ff"Ta5d6ffapplicationTa5d6ff"Ta5d6ff:{Ta5d6ff"Ta5d6ffbin_fileTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffapp.binTa5d6ff"Ta5d6ff,Ta5d6ff"Ta5d6ffdat_fileTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffapp.datTa5d6ff"Ta5d6ff}}}Ta5d6ff"""Tb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffapp.binTa5d6ff"Tb4b4b4, Te6edf3manifestTb4b4b4.Te6edf3manifestTb4b4b4.Te6edf3applicationTff7b72?.Te6edf3binFileTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffapp.datTa5d6ff"Tb4b4b4, Te6edf3manifestTb4b4b4.Te6edf3manifestTb4b4b4.Te6edf3applicationTff7b72?.Te6edf3datFileTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuManifest deserializes softdevice_bootloader entry`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3manifest Tff7b72=
Te6edf3jsonTb4b4b4.Te6edf3decodeFromStringTff7b72<Te6edf3DfuManifestTff7b72>Tb4b4b4(
Ta5d6ff"""Ta5d6ff{Ta5d6ff"Ta5d6ffmanifestTa5d6ff"Ta5d6ff:{Ta5d6ff"Ta5d6ffsoftdevice_bootloaderTa5d6ff"Ta5d6ff:{Ta5d6ff"Ta5d6ffbin_fileTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffsd.binTa5d6ff"Ta5d6ff,Ta5d6ff"Ta5d6ffdat_fileTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffsd.datTa5d6ff"Ta5d6ff}}}Ta5d6ff"""Tb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffsd.binTa5d6ff"Tb4b4b4, Te6edf3manifestTb4b4b4.Te6edf3manifestTb4b4b4.Te6edf3softdeviceBootloaderTff7b72?.Te6edf3binFileTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuManifest ignores unknown keys`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3manifest Tff7b72=
Te6edf3jsonTb4b4b4.Te6edf3decodeFromStringTff7b72<Te6edf3DfuManifestTff7b72>Tb4b4b4(
Ta5d6ff"""Ta5d6ff{Ta5d6ff"Ta5d6ffmanifestTa5d6ff"Ta5d6ff:{Ta5d6ff"Ta5d6ffapplicationTa5d6ff"Ta5d6ff:{Ta5d6ff"Ta5d6ffbin_fileTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffa.binTa5d6ff"Ta5d6ff,Ta5d6ff"Ta5d6ffdat_fileTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffa.datTa5d6ff"Ta5d6ff},Ta5d6ff"Ta5d6ffunknown_fieldTa5d6ff"Ta5d6ff:Ta5d6ff"Ta5d6ffignoredTa5d6ff"Ta5d6ff}}Ta5d6ff"""Tb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffa.binTa5d6ff"Tb4b4b4, Te6edf3manifestTb4b4b4.Te6edf3manifestTb4b4b4.Te6edf3primaryEntryTff7b72?.Te6edf3binFileTb4b4b4)
Tb4b4b4}
T8b949e// ββ DfuManifestContent.primaryEntry priority ββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`primaryEntry prefers application over all others`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3content Tff7b72=
Te6edf3DfuManifestContentTb4b4b4(
Te6edf3application Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffapp.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffapp.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3softdeviceBootloader Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffsd_bl.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsd_bl.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3bootloader Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffboot.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffboot.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3softdevice Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffsd.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsd.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffapp.binTa5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4.Te6edf3primaryEntryTff7b72?.Te6edf3binFileTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`primaryEntry falls back to softdevice_bootloader`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3content Tff7b72=
Te6edf3DfuManifestContentTb4b4b4(
Te6edf3softdeviceBootloader Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffsd_bl.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsd_bl.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3bootloader Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffboot.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffboot.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffsd_bl.binTa5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4.Te6edf3primaryEntryTff7b72?.Te6edf3binFileTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`primaryEntry falls back to bootloader`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3content Tff7b72=
Te6edf3DfuManifestContentTb4b4b4(
Te6edf3bootloader Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffboot.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffboot.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3softdevice Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffsd.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsd.datTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffboot.binTa5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4.Te6edf3primaryEntryTff7b72?.Te6edf3binFileTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`primaryEntry falls back to softdevice`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3content Tff7b72= Te6edf3DfuManifestContentTb4b4b4(Te6edf3softdevice Tff7b72= Te6edf3DfuManifestEntryTb4b4b4(Ta5d6ff"Ta5d6ffsd.binTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsd.datTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffsd.binTa5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4.Te6edf3primaryEntryTff7b72?.Te6edf3binFileTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`primaryEntry is null when all entries are null`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertNullTb4b4b4(Te6edf3DfuManifestContentTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3primaryEntryTb4b4b4)
Tb4b4b4}
T8b949e// ββ DfuException messages βββββββββββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuException ProtocolError includes opcode and result code in message`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3e Tff7b72= Te6edf3DfuExceptionTb4b4b4.Te6edf3ProtocolErrorTb4b4b4(Te6edf3opcode Tff7b72= T79c0ff0Te6edf3x01Tb4b4b4, Te6edf3resultCode Tff7b72= T79c0ff0Te6edf3x05Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff0x01Ta5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should contain opcodeTa5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff0x05Ta5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should contain result codeTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuException ChecksumMismatch formats hex values in message`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3e Tff7b72= Te6edf3DfuExceptionTb4b4b4.Te6edf3ChecksumMismatchTb4b4b4(Te6edf3expected Tff7b72= T79c0ff0Te6edf3xDEADBEEFTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3actual Tff7b72= T79c0ff0Te6edf3x12345678Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffdeadbeefTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should contain expected CRCTa5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff12345678Ta5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should contain actual CRCTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuZipPackage equality is content-based`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3DfuZipPackageTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4, Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x02Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3DfuZipPackageTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4, Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x02Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuZipPackage inequality when content differs`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3DfuZipPackageTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4, Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x02Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3DfuZipPackageTb4b4b4(Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4)Tb4b4b4, Te6edf3byteArrayOfTb4b4b4(T79c0ff0Te6edf3x03Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3a Tff7b72!Tff7b72= Te6edf3bTb4b4b4)
Tb4b4b4}
T8b949e// ββ Extended error codes βββββββββββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Failure with extended error when result is EXT_ERROR`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// [RESPONSE_CODE, CREATE, EXT_ERROR, SD_VERSION_FAILURE]
Tff7b72val Te6edf3data Tff7b72=
Te6edf3byteArrayOfTb4b4b4(
Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4,
Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4,
Te6edf3DfuResultCodeTb4b4b4.Te6edf3EXT_ERRORTb4b4b4,
Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3SD_VERSION_FAILURETb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4, Te6edf3resultTb4b4b4.Te6edf3opcodeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuResultCodeTb4b4b4.Te6edf3EXT_ERRORTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3resultCodeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3SD_VERSION_FAILURETb4b4b4, Te6edf3resultTb4b4b4.Te6edf3extendedErrorTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Failure without extended error when EXT_ERROR but no extra byte`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Only 3 bytes β no room for extended error byte
Tff7b72val Te6edf3data Tff7b72= Te6edf3byteArrayOfTb4b4b4(Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4, Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4, Te6edf3DfuResultCodeTb4b4b4.Te6edf3EXT_ERRORTb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuResultCodeTb4b4b4.Te6edf3EXT_ERRORTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3resultCodeTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3extendedErrorTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`parse returns Failure without extended error for non-EXT_ERROR codes`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3data Tff7b72=
Te6edf3byteArrayOfTb4b4b4(
Te6edf3DfuOpcodeTb4b4b4.Te6edf3RESPONSE_CODETb4b4b4,
Te6edf3DfuOpcodeTb4b4b4.Te6edf3CREATETb4b4b4,
Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_OBJECTTb4b4b4,
T79c0ff0Te6edf3x07Tb4b4b4, T8b949e// extra byte that should be ignored
Tb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTff7b72>Tb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DfuResultCodeTb4b4b4.Te6edf3INVALID_OBJECTTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3resultCodeTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3extendedErrorTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuExtendedError describe returns known descriptions`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffSD version failureTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3SD_VERSION_FAILURETb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffSignature missingTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3SIGNATURE_MISSINGTb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffVerification failedTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3VERIFICATION_FAILEDTb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffInsufficient spaceTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3INSUFFICIENT_SPACETb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffInit command invalidTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3INIT_COMMAND_INVALIDTb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffFW version failureTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3FW_VERSION_FAILURETb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffHW version failureTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3HW_VERSION_FAILURETb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffWrong hash typeTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3WRONG_HASH_TYPETb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffHash failedTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3HASH_FAILEDTb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffWrong signature typeTa5d6ff"Tb4b4b4, Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3WRONG_SIGNATURE_TYPETb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuExtendedError describe returns hex for unknown code`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3desc Tff7b72= Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3describeTb4b4b4(T79c0ff0Te6edf3x7FTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3descTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff0x7fTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffShould contain hex code: Tffd700$Te6edf3descTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuException ProtocolError includes extended error description in message`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3e Tff7b72=
Te6edf3DfuExceptionTb4b4b4.Te6edf3ProtocolErrorTb4b4b4(
Te6edf3opcode Tff7b72= Te6edf3DfuOpcodeTb4b4b4.Te6edf3EXECUTETb4b4b4,
Te6edf3resultCode Tff7b72= Te6edf3DfuResultCodeTb4b4b4.Te6edf3EXT_ERRORTb4b4b4,
Te6edf3extendedError Tff7b72= Te6edf3DfuExtendedErrorTb4b4b4.Te6edf3SD_VERSION_FAILURETb4b4b4,
Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffSD version failureTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should contain extended error: Tffd700${Te6edf3eTb4b4b4.Te6edf3messageTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff0x0bTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should contain result code 0x0b: Tffd700${Te6edf3eTb4b4b4.Te6edf3messageTffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`DfuException ProtocolError without extended error omits ext field`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3e Tff7b72= Te6edf3DfuExceptionTb4b4b4.Te6edf3ProtocolErrorTb4b4b4(Te6edf3opcode Tff7b72= T79c0ff0Te6edf3x01Tb4b4b4, Te6edf3resultCode Tff7b72= T79c0ff0Te6edf3x05Tb4b4b4, Te6edf3extendedError Tff7b72= Tff7b72nullTb4b4b4)
Te6edf3assertTrueTb4b4b4(Tff7b72!Te6edf3eTb4b4b4.Te6edf3messageTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffext=Ta5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffMessage should not contain ext= when null: Tffd700${Te6edf3eTb4b4b4.Te6edf3messageTffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
T8b949e// ββ DfuResponse Failure equality βββββββββββββββββββββββββββββββββββββββββ
Tf0883e@Test
Tff7b72fun Td2a8ff`Failure with same extended error is equal`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x0BTb4b4b4, T79c0ff0Te6edf3x07Tb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x0BTb4b4b4, T79c0ff0Te6edf3x07Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`Failure with null vs non-null extended error is not equal`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x0BTb4b4b4, Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3DfuResponseTb4b4b4.Te6edf3FailureTb4b4b4(T79c0ff0Te6edf3x01Tb4b4b4, T79c0ff0Te6edf3x0BTb4b4b4, T79c0ff0Te6edf3x07Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3a Tff7b72!Tff7b72= Te6edf3bTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.15s